package com.mall.websocket;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.mall.entity.Message;
import com.mall.entity.User;
import com.mall.mapper.MessageMapper;
import com.mall.mapper.UserMapper;
import com.mall.security.CustomUserDetailsService;
import com.mall.util.JwtUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.*;

import java.io.IOException;
import java.time.LocalDateTime;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 聊天WebSocket处理器
 * 
 * @author mall
 * @since 2024-01-01
 */
@Slf4j
@Component
public class ChatWebSocketHandler implements WebSocketHandler {

    @Autowired
    private MessageMapper messageMapper;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private JwtUtil jwtUtil;

    @Autowired
    private ObjectMapper objectMapper;

    // 存储在线用户会话
    private final Map<Long, WebSocketSession> userSessions = new ConcurrentHashMap<>();

    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        log.info("WebSocket连接建立: {}", session.getId());
        
        // 从查询参数中获取token
        String token = session.getUri().getQuery();
        if (token != null && token.startsWith("token=")) {
            token = token.substring(6);
            try {
                Long userId = jwtUtil.getUserIdFromToken(token);
                String username = jwtUtil.getUsernameFromToken(token);
                
                // 验证token有效性
                if (jwtUtil.validateToken(token, username)) {
                    // 存储用户会话
                    userSessions.put(userId, session);
                    session.getAttributes().put("userId", userId);
                    session.getAttributes().put("username", username);
                    
                    log.info("用户 {} 连接成功，当前在线用户数: {}", username, userSessions.size());
                    
                    // 发送连接成功消息
                    sendMessage(session, createSystemMessage("连接成功"));
                } else {
                    log.warn("无效的token，关闭连接");
                    session.close();
                }
            } catch (Exception e) {
                log.error("token解析失败: {}", e.getMessage());
                session.close();
            }
        } else {
            log.warn("未提供token，关闭连接");
            session.close();
        }
    }

    @Override
    public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) throws Exception {
        if (message instanceof TextMessage) {
            String payload = ((TextMessage) message).getPayload();
            log.info("收到消息: {}", payload);
            
            try {
                // 解析消息
                Map<String, Object> messageData = objectMapper.readValue(payload, Map.class);
                handleChatMessage(session, messageData);
            } catch (Exception e) {
                log.error("消息处理失败: {}", e.getMessage());
                sendMessage(session, createErrorMessage("消息格式错误"));
            }
        }
    }

    @Override
    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
        log.error("WebSocket传输错误: {}", exception.getMessage());
        removeUserSession(session);
    }

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception {
        log.info("WebSocket连接关闭: {}, 状态: {}", session.getId(), closeStatus);
        removeUserSession(session);
    }

    @Override
    public boolean supportsPartialMessages() {
        return false;
    }

    /**
     * 处理聊天消息
     */
    private void handleChatMessage(WebSocketSession session, Map<String, Object> messageData) throws IOException {
        Long senderId = (Long) session.getAttributes().get("userId");
        String messageType = (String) messageData.get("messageType");
        String content = (String) messageData.get("content");
        Long receiverId = messageData.get("receiverId") != null ? 
            Long.valueOf(messageData.get("receiverId").toString()) : null;
        String commandType = (String) messageData.get("commandType");
        String commandParams = (String) messageData.get("commandParams");

        // 创建消息实体
        Message message = new Message();
        message.setSenderId(senderId);
        message.setReceiverId(receiverId);
        message.setMessageType(messageType);
        message.setContent(content);
        message.setStatus(0);
        message.setIsBroadcast(receiverId == null ? 1 : 0);
        message.setCommandType(commandType);
        message.setCommandParams(commandParams);
        message.setCreateTime(LocalDateTime.now());

        // 保存消息到数据库
        messageMapper.insert(message);

        // 处理指令消息
        if (commandType != null) {
            handleCommand(session, message);
        }

        // 发送消息给接收者
        if (receiverId != null) {
            sendMessageToUser(receiverId, createChatMessage(message));
        } else {
            // 群发消息（这里简化处理，实际应该根据业务逻辑确定接收者）
            broadcastMessage(createChatMessage(message));
        }
    }

    /**
     * 处理指令
     */
    private void handleCommand(WebSocketSession session, Message message) throws IOException {
        String commandType = message.getCommandType();
        Long senderId = message.getSenderId();
        
        switch (commandType) {
            case "QUERY_ORDER":
                handleQueryOrder(session, senderId, message.getCommandParams());
                break;
            case "APPLY_REFUND":
                handleApplyRefund(session, senderId, message.getCommandParams());
                break;
            default:
                sendMessage(session, createErrorMessage("未知指令类型"));
        }
    }

    /**
     * 处理查询订单指令
     */
    private void handleQueryOrder(WebSocketSession session, Long userId, String params) throws IOException {
        // 这里应该调用订单服务查询订单
        // 简化处理，返回模拟数据
        String response = "查询订单功能开发中，用户ID: " + userId;
        sendMessage(session, createSystemMessage(response));
    }

    /**
     * 处理申请退款指令
     */
    private void handleApplyRefund(WebSocketSession session, Long userId, String params) throws IOException {
        // 这里应该调用退款服务处理退款申请
        // 简化处理，返回模拟数据
        String response = "退款申请已提交，用户ID: " + userId + "，参数: " + params;
        sendMessage(session, createSystemMessage(response));
    }

    /**
     * 发送消息给指定用户
     */
    public void sendMessageToUser(Long userId, String message) {
        WebSocketSession session = userSessions.get(userId);
        if (session != null && session.isOpen()) {
            try {
                sendMessage(session, message);
            } catch (IOException e) {
                log.error("发送消息失败: {}", e.getMessage());
                removeUserSession(session);
            }
        }
    }

    /**
     * 群发消息
     */
    public void broadcastMessage(String message) {
        userSessions.values().forEach(session -> {
            if (session.isOpen()) {
                try {
                    sendMessage(session, message);
                } catch (IOException e) {
                    log.error("群发消息失败: {}", e.getMessage());
                }
            }
        });
    }

    /**
     * 发送消息
     */
    private void sendMessage(WebSocketSession session, String message) throws IOException {
        if (session.isOpen()) {
            session.sendMessage(new TextMessage(message));
        }
    }

    /**
     * 移除用户会话
     */
    private void removeUserSession(WebSocketSession session) {
        Long userId = (Long) session.getAttributes().get("userId");
        if (userId != null) {
            userSessions.remove(userId);
            log.info("用户 {} 断开连接，当前在线用户数: {}", userId, userSessions.size());
        }
    }

    /**
     * 创建聊天消息
     */
    private String createChatMessage(Message message) {
        try {
            Map<String, Object> messageData = new java.util.HashMap<>();
            messageData.put("type", "chat");
            messageData.put("messageId", message.getId());
            messageData.put("senderId", message.getSenderId());
            messageData.put("receiverId", message.getReceiverId());
            messageData.put("messageType", message.getMessageType());
            messageData.put("content", message.getContent());
            messageData.put("createTime", message.getCreateTime());
            messageData.put("commandType", message.getCommandType());
            messageData.put("commandParams", message.getCommandParams());
            
            return objectMapper.writeValueAsString(messageData);
        } catch (Exception e) {
            log.error("创建聊天消息失败: {}", e.getMessage());
            return "{}";
        }
    }

    /**
     * 创建系统消息
     */
    private String createSystemMessage(String content) {
        try {
            Map<String, Object> messageData = new java.util.HashMap<>();
            messageData.put("type", "system");
            messageData.put("content", content);
            messageData.put("timestamp", System.currentTimeMillis());
            
            return objectMapper.writeValueAsString(messageData);
        } catch (Exception e) {
            log.error("创建系统消息失败: {}", e.getMessage());
            return "{}";
        }
    }

    /**
     * 创建错误消息
     */
    private String createErrorMessage(String content) {
        try {
            Map<String, Object> messageData = new java.util.HashMap<>();
            messageData.put("type", "error");
            messageData.put("content", content);
            messageData.put("timestamp", System.currentTimeMillis());
            
            return objectMapper.writeValueAsString(messageData);
        } catch (Exception e) {
            log.error("创建错误消息失败: {}", e.getMessage());
            return "{}";
        }
    }

    /**
     * 获取在线用户数
     */
    public int getOnlineUserCount() {
        return userSessions.size();
    }

    /**
     * 获取在线用户列表
     */
    public Map<Long, WebSocketSession> getOnlineUsers() {
        return new ConcurrentHashMap<>(userSessions);
    }
}
